/**
 * README
 * 
 * Modificacion de la biblioteca jWave disponible en http://code.google.com/p/jwave/
 * Convertidos los tipos de datos a float para agilizar el tratamiendo de grandes arrays de datos
 * como son los que se tratan en analisis genomicos.
 * Los autores originales de las funciones y del código de la biblioteca cuando fue seleccionada en
 * Abril de 2012 eran:
 *        Christian Scheiblich
 *        Thomas Leduc
 *        sashi
 *        Pol Kennel
 *        Thomas Haider
 *        
 * Por supuesto, todo el merito, honores y demas menciones sobre esta adaptacion les corresponden a ellos
 * y nada mas que a ellos.
 * 
 * 
 * This is a modified version of jWave, available in http://code.google.com/p/jwave/
 * It has been replace the double datatype with float for performance reasons in very big arrays used in
 * bioinformatics like genomic analysis.
 * Original authors of functions and the library when it has been selected in 2012's April were:
 *        Christian Scheiblich
 *        Thomas Leduc
 *        sashi
 *        Pol Kennel
 *        Thomas Haider
 *        
 * Of course, all the merits and mentions about this adaptation have corresponded to them.
 * 
 */

package ev.maths.handlers.wavelets;

/**
 * Clase básica para un wavelet. Contiene los coeficientes del wavelet, la función de escala
 * el tamaño básico, el método para la transformada y para la transformada inversa.
 * 
 * @date 01.08.2012
 * @author Enrique Vázquez de Luis
 */
public abstract class Wavelet implements WaveletInterface {

  /**
   * Tamaño mínimo de la wavelet y factor de escala
   */
  protected int _waveLength;

  /**
   * Coeficientes de la wavelet. Función de la misma.
   */
  protected float[ ] _coeffs;

  /**
   * Coeficientes de escala. Función de escala
   */
  protected float[ ] _scales;

  /**
   * Contructor con los valores por defecto de los atributos.
   * 
   * @date 01.08.2012
   * @author Enrique Vázquez de Luis
   */
  public Wavelet( ) {
    _waveLength = 0;
    _coeffs = null;
    _scales = null;
  } // Wavelet

  /**
   * Realiza la transformada de un array devolviendo otro del mismo tamaño que
   * contiene los coeficientes del dominio de Hilbert.
   * El tamaño debe ser una potencia de 2.
   * 
   * @date 01.08.2012
   * @author Enrique Vázquez de Luis
   * @param arrTime Array que contiene la función en el dominio del tiempo
   * @return Coeficientes que representan el dominio de la frecuencia
   */
  public float[ ] forward( float[ ] arrTime ) {

    float[ ] arrHilb = new float[ arrTime.length ];

    int k = 0;
    int h = arrTime.length >> 1;

    for( int i = 0; i < h; i++ ) {

      for( int j = 0; j < _waveLength; j++ ) {

        k = ( i << 1 ) + j;
        while( k >= arrTime.length ) k -= arrTime.length;

        arrHilb[ i ] += arrTime[ k ] * _scales[ j ];
        arrHilb[ i + h ] += arrTime[ k ] * _coeffs[ j ];

      } // wavelet

    } // h

    return arrHilb;
  } // forward

  /**
   * Realiza la transformada inversa de un array con coeficientes del dominio
   * de Hilbert a uno con una funci�n en el dominio del tiempo del mismo tama�o.
   * El tama�o debe ser potencia de 2.
   * 
   * @date 01.08.2012
   * @author Enrique Vázquez de Luis
   * @param arrHilb Array con los coeficientes del dominio de la frecuencia.
   * @return Coeficientes que representan el dominio del tiempo.
   */
  public float[ ] reverse( float[ ] arrHilb ) {

    float[ ] arrTime = new float[ arrHilb.length ];

    int k = 0;
    int h = arrHilb.length >> 1;
    for( int i = 0; i < h; i++ ) {

      for( int j = 0; j < _waveLength; j++ ) {

        k = ( i << 1 ) + j;
        while( k >= arrHilb.length ) k -= arrHilb.length;

        arrTime[ k ] += ( arrHilb[ i ] * _scales[ j ] + arrHilb[ i + h ] * _coeffs[ j ] ); 

      } // wavelet

    } //  h

    return arrTime;
  } // reverse

  /**
   * Devuelve el tamaño mínimo de la "onda" para poder aplicarle la wavelet.
   * 
   * @date 01.08.2012
   * @author Enrique Vázquez de Luis
   * @return El tamaño de la wavelet.
   */
  public int getWaveLength( ) {
    return _waveLength;
  } // getWaveLength

  /**
   * Devuelve el número de coeficientes de la wavelet.
   * 
   * @date 01.08.2012
   * @author Enrique Vázquez de Luis
   * @return El número de coeficientes.
   */
  public int getLength( ) {
    return _coeffs.length;
  } // getLength

  /**
   * Devuelve un array con los coeficientes de la wavelet.
   * 
   * @date 01.08.2012
   * @author Enrique Vázquez de Luis
   * @return Array con los coeficientes de la wavelet.
   */
  public float[ ] getCoeffs( ) {
    float[ ] coeffs = new float[ _coeffs.length ];
    for( int c = 0; c < _coeffs.length; c++ )
      coeffs[ c ] = _coeffs[ c ];
    return coeffs;
  } // getCoeffs

  /**
   * Devuelve un array con los factores de escala.
   * 
   * @date 01.08.2012
   * @author Enrique Vázquez de Luis
   * @return Array con los valores de escala.
   */
  public float[ ] getScales( ) {
    float[ ] scales = new float[ _scales.length ];
    for( int s = 0; s < _scales.length; s++ )
      scales[ s ] = _scales[ s ];
    return scales;
  } // getScales

} // class
